/**
  *		Ankara University 
  * 	Computer Engineering Department
  *		Lab 5
  *		Subject : Linear Quotient 
  * 	Author : Haydar Kulekci
  *
  */

#include<stdio.h>
#include<stdlib.h>

#define DEFAULT_TABLE_SIZE 5

int *createTable(int tableSize){
	int i;
	int *table;
	table = NULL;
	table = (int*) malloc( tableSize * sizeof(int) );
	for (i=0 ;i < tableSize ;i++ ){
		table[i] = -1;
	}
}

int *switchArray(int *old, int tableSize){
	int i;
	newAr = (int*) malloc( sizeof(int) * tableSize );
	for (i=0;i<tableSize ;i++ ){
		newAr[i] = old[i];
	}
	return newAr;
}

// return num of elements
int loadFromFile(int *tk,int tableSize){
	FILE *fp;
	int i = 0,sc,numOfElements = 0;
	fp = fopen("numbers.txt","r");
	do{
		fscanf(fp,"%5d",&sc);
		tk[i] = sc;
		if (sc >= 0) numOfElements++;
		printf("%d\t",sc);
		if (i >= tableSize){
			break;
		}
		i++;
	}while(!feof(fp));
	printf("File is loaded!\n");
	return numOfElements;
}

void saveToFile(const int *tk, int tableSize){
	FILE *fp;
	int i = 0;
	
	fp = fopen("numbers.txt","w");
	for (i=0;i<tableSize;i++){
		fprintf(fp,"%5d",tk[i]);
	}
	fclose(fp);
}

int hash(int num,int tableSize){
	return num%tableSize;
}

int hashTo(int num,int tableSize){
	return (( (num/tableSize)%tableSize == 0 )?(1):((num/tableSize)%tableSize));
}

int getTableSize(int old, int now){
	int newTableSize, temp_pri, i, j;
	if (now == 0)
	   return old;
	if (old < 2){
		return 2;
	}
	for (i = old + 1 ;i < 1000 ;i++ ){
		temp_pri = 0;
		for (j=i-1; j>=2 ;j-- ){
			if (i%j == 0){
				temp_pri = 1;
			}
		}
		if (temp_pri == 0){
			return i;
		}
	}
	return 2;
}

int checkPackingFactor(int numOfElements,int tableSize){
	return ((numOfElements / tableSize * 100 < 95)?(1):(0)); 
}

int insertNumber(int *table,int tableSize,int number){
	//TODO: Now you can add same number on the table. Fix it!
	int dn = hash(number, tableSize);
	int inc = hashTo(number, tableSize);
	int dn2 = (dn + inc)%tableSize;
	int turning = 0;
	printf("  -- %d icin denendi.(1)\n",dn);
	if (table[dn] == -1){
		table[dn] = number;
		return 1;
	}else{
		while(table[dn2] > 0){
	        printf("  -- %d icin denendi.(2)\n",dn2);
	        if (table[dn2] < 0){break;}
			dn2 = (dn2 + inc) % tableSize;
			if (turning == 20){
				return 0;
			}
			turning++;
		}
		printf("  -- Son olarak %d icin denendi.(3)\n",dn2);
		if (table[dn2] == -1)
			table[dn2] = number;
	}
	return 1;
}

int searchNumber(int *table,int tableSize,int number){
	int dn = hash(number, tableSize);
	int inc = hashTo(number, tableSize);
	int dn2 = (dn + inc)%tableSize;
	int turning = 0;
	printf("  -- %d icin denendi.(1)\n",dn);
	if (table[dn] == number){
		return dn;
	}else if (table[dn] == -1){
		  return -1;	  
    }else{
		while(table[dn2] != -1){
	        printf("  -- %d icin denendi.(2)\n",dn2);
	        if (table[dn2] == -1){return -1;}
	        if (table[dn2] == number) return dn2;
			dn2 = (dn2 + inc) % tableSize;
			if (turning == 20){
				return -1;
			}
			turning++;
		}
		printf("  -- Son olarak %d icin denendi.(3)\n",dn2);
		if (table[dn2] == number)
			return dn2;
	}
	return -1;
}

int deleteNumber(int *table,int tableSize,int number){
	int tmp = searchNumber(table,tableSize,number);
	if (tmp != -1){
	    table[tmp] = -2;
	    return tmp;
    }else{
		return -1;	  
    }
}


void insertElementsFromOldToNewTable(int *tempTable,int tempTableSize,int *table,int tableSize){
	int i;
	for (i = 0;i<tempTableSize ;i++ ){
		insertNumber(table,tableSize,tempTable[i]);
	}
}

void print(int *table, int tableSize){
	int i;
	printf("\n");
	for (i = 0; i<tableSize ;i++ ){
		if (table[i] < -1)
		   printf("%2d -  ~\n",i);
		else if (table[i] < 0)
		    printf("%2d -   \n",i);
        else
			printf("%2d -%3d\n",i,table[i]);
	}
	printf("\n");
}

int check_numOfElements(int *table,int tableSize){
	int i,j = 0;
	for (i = 0; i<tableSize ;i++ ){
		if (table[i] >= 0)
		    j++;
	}
	return j;
}

void printMenu(){
	 printf("\n -- Press \"a\" to Load From File!\n");	 
	 printf(" -- Press \"b\" to Insert!\n");	 
	 printf(" -- Press \"c\" to Delete!\n");	 
	 printf(" -- Press \"d\" to Search!\n");	 
	 printf(" -- Press \"e\" to Save To File!\n");
	 printf(" -- Press \"f\" to Reset Table!\n");
	 printf(" -- Press \"g\" to Print Table!\n");
	 printf(" Choose one of : ");	 
}



int main(){
	int tableSize = DEFAULT_TABLE_SIZE, tempTableSize = DEFAULT_TABLE_SIZE;
	int *table = NULL,*tempTable;
	int number,numOfElements = 0;
	int i,result,repeat = 0;
	char choice;
	
	
	tableSize = getTableSize(tableSize,0);
	// Create Table
	table = (int*) malloc( tableSize * sizeof(int) );
	for (i=0 ;i < tableSize ;i++ ){ table[i] = -1; }
	
	//print(table,tableSize);

	while (1){ // Start Insert
	
		printMenu();
		if (repeat != 1){
		   scanf("%c",&choice);
		   repeat = 0;
		}
		
		if (choice == 'a' || choice == 'A'){
		     //load from file
             printf("Enter number of number in the file : ");
		     scanf("%d",&result);
		     table = NULL;
		     tableSize = result;
		     table = (int*) malloc( result * sizeof(int) );
             for (i=0 ;i < result ;i++ ){ table[i] = -1; }
		     numOfElements = loadFromFile(table,result);  		   
        }else if (choice == 'f' || choice == 'F'){
		    // Reseting
		    table = NULL;
		    tempTable = NULL;
		    tableSize = DEFAULT_TABLE_SIZE;
		    tempTableSize = DEFAULT_TABLE_SIZE;
		    numOfElements = 0;
		    tableSize = getTableSize(tableSize,0);
		    
			// Create Table
			table = (int*) malloc( tableSize * sizeof(int) );
			for (i=0 ;i < tableSize ;i++ ){ table[i] = -1; }
			
			print(table,tableSize);	  
        }else if (choice == 'b' || choice == 'B'){
	
	
			printf("Write an integer [0-*] : ");
			scanf("%d",&number);
			
			if ( number < 0 ){
				repeat = 1;
				continue;
			}else{
				if (checkPackingFactor(numOfElements+1,tableSize) == 0){
				    // switch Array
				    tempTable = (int*) malloc( sizeof(int) * tableSize );
					for (i=0;i<tableSize ;i++ ){ tempTable[i] = table[i];}
					//switchArray(table,tempTable,tableSize);
					
					tempTableSize = tableSize;
					tableSize = getTableSize(tableSize,1);
					printf("New Table Size : %d\n",tableSize);
					
					printf("Old : ");
					print(tempTable,tempTableSize);
					//createTable(table,tableSize);
					// Create Table
					table = NULL;
					table = (int*) malloc( tableSize * sizeof(int) );
					for (i=0 ;i < tableSize ;i++ ){ table[i] = -1; }
					
					//insertElementsFromOldToNewTable
					for (i = 0;i < tempTableSize ;i++ ){	
						if (tempTable[i] == -1){continue;}
						result = insertNumber(table,tableSize,tempTable[i]);
						if (result == 0) numOfElements--; 
					}
					//insertElementsFromOldToNewTable(tempTable,tempTableSize,table,tableSize);
					//newAr = (int*) malloc( sizeof(int) * tableSize );
					//for (i=0;i<tableSize ;i++ ){	newAr[i] = old[i]; }
				}
				result = insertNumber(table, tableSize, number);
				if (result == 0) numOfElements--;
			}
			printf("New : ");
			print(table,tableSize);
			
			numOfElements = numOfElements + 1;
			printf("numOfElements = %d\n",numOfElements);
			numOfElements = check_numOfElements(table,tableSize);
			printf("numOfElements = %d\n",numOfElements);
	     
		 }else if (choice == 'c' || choice == 'C'){
		 	printf("Write an integer [0-*] : ");
			scanf("%d",&number);
			
			result = deleteNumber(table,tableSize,number);
			if (result != -1){
		 	      printf("Deleted from %d!",result);
			}else{
				  printf("Not deleted! (Not found or sometihng is wrong!)");
	        }
			
	     }else if (choice == 'd' || choice == 'D'){
		 	printf("Write an integer [0-*] : ");
			scanf("%d",&number);
			
			result = searchNumber(table,tableSize,number);
			if (result != -1){
		 	      printf("Found on %d!",result);
			}else{
				  printf("Not found! (Not found or sometihng is wrong!)");
	        }
		 }else if (choice == 'e' || choice == 'E'){
         	   saveToFile(table,tableSize);
		 }else if (choice == 'g' || choice == 'G'){
         	   print(table,tableSize);
		 }else
		 	  break;
		 fflush(stdin);
	}
	free(table);
	return 0;
}
